#include "LightFile.h"
#include "LightFileStorageManager.h"
#include "TagList.h"
#include "ShapeDef.h"
#include "SpriteDef.h"
#include "SceneObject.h"
#include "LightAbstractRenderer.h"
#include "TimelineObject.h"

namespace LightPlayer {

	LightFile::LightFile(){
		init();
	}

	void LightFile::init(){
		m_pRenderer = NULL;
		m_Stream.init();
		m_CharacterList.init();
		clearDisplayList();
		m_ActionList.clear();
		m_FrameLabelList.clear();
		m_As2VM.init();
		m_VarList.clear();
		m_ObjectPool.clear();
		m_TimelineObjectPool.clear();
		m_frameSize = RECT();
		m_frameRate = 0.0f;
		m_frameDuration = 0.0f;
		m_timeSinceLastFrame = 0.0f;
		m_frameNumber = 0;
		m_Actualframe = 0;
		m_IsPlaying = true;
	}


	LightFile::~LightFile(){

	}

	void LightFile::open( const char* FileName ){
		const FileMapInfo& file = LightFileStorageManager::getInstance()->getLoadedSwfFile( FileName );
		if( file == FileMapInfo::EMPTY_FILE ){
			printf("Error Lightfile::open => canno't open file :%s\n",FileName);
			return;
		}
		m_Stream.init( file.buffer, file.length );

		uint32 prev_offset = m_Stream.getCurrentOffset();

		m_Stream.read_u32(); // skip Header
		m_Stream.read_u32(); // skip file size

		m_frameSize.readFromStream(&m_Stream);
		m_frameRate = m_Stream.read_fixed16();
		m_frameDuration = 1 / m_frameRate;
		m_timeSinceLastFrame = 0.0f;
		m_frameNumber = m_Stream.read_u16();
		m_Actualframe = 0;

		uint32 header_size = m_Stream.getCurrentOffset() - prev_offset;
		m_Stream.init( m_Stream.getCurrentPosition(), file.length - header_size );

		collectFrameLabels();
		firstUpdate();
	}

	void LightFile::update( float dt ){
		m_timeSinceLastFrame += dt;
		while( m_timeSinceLastFrame >= m_frameDuration ){
			
			Parser::update(dt);

			m_timeSinceLastFrame -= m_frameDuration;
		}
	}

	void LightFile::draw(){
		LightAbstractRenderer* pRenderer = getRenderer();
		if(pRenderer){
			pRenderer->beginDraw();

			MATRIX mat;
			mat._23 = m_frameSize.Ymax;
			mat._22 = -1;

			pRenderer->pushMatrix( mat );

			m_DsiplayList.draw( pRenderer );

			pRenderer->popMatrix();

			pRenderer->endDraw();
		}
	}

	SceneObject* LightFile::getNewSceneObject(){
		SceneObject* obj = m_ObjectPool.getNew();
		obj->init();
		return obj;
	}

	TimelineObject* LightFile::getNewTimelineObject(){
		TimelineObject* obj = m_TimelineObjectPool.getNew();
		obj->init();
		return obj;
	}

	void LightFile::freeObject( SceneObject* object ){
		if(object && object->getType() == eSceneObject ){
			m_ObjectPool.FreeObject( object );
		}
		else if(object && object->getType() == eTimelineObject ){
			TimelineObject* timeline = (TimelineObject* )object;
			m_TimelineObjectPool.FreeObject( timeline );
		}
		else{
			assert(0);
		}
	}

	void LightFile::clearDisplayList(){
		display_list_type::iterator it = m_DsiplayList.list.begin();
		for (; it != m_DsiplayList.list.end(); ++it ){
			freeObject( it->second );
		}
		m_DsiplayList.clear();
	}

	void LightFile::collectFrameLabels(){
		m_FrameLabelList.clear();

		Stream strCpy = m_Stream;
		strCpy.rewind();

		uint16 cur_frame = 1;
		TAG tag;
		do{
			tag.readFromStream( &strCpy );

			if( tag.type == eShowFrame ){
				cur_frame++;
			}

			if( tag.type == eFrameLabel ){
				const char* label = (const char*) strCpy.getCurrentPosition();
				m_FrameLabelList.push_back( type_label_list(label,cur_frame) );
			}

			strCpy.skip_byte( tag.size );
		} while ( tag.type != eEnd );
	}

	uint16 LightFile::getFrameForLabel( const char* label ){
		FrameLabelList::iterator it = m_FrameLabelList.begin();
		for (; it != m_FrameLabelList.end(); ++it){
			if( strcmp( it->first, label ) == 0 ){
				return it->second;
			}
		}
		return 0;
	}

	As2Var LightFile::getVar( const char* name ){
		string nameKey = name;
		if( m_VarList.find( nameKey ) != m_VarList.end() ){
			return m_VarList[nameKey];
		}
		return As2Var();
	}

	void LightFile::setVar( const char* name, const As2Var& value ){
		string nameKey = name;
		m_VarList[nameKey] = value;
	}

	As2Var LightFile::getProperty( PropertyEnum property ){
		As2Var return_value;
		return_value.set_undef();
		switch( property ){
		default: break;
		case _X:					{ return_value.set_float(0.0f);  break; }
		case _Y:					{ return_value.set_float(0.0f);  break; }
		case _xscale:				{ return_value.set_float(1.0f);  break; }
		case _yscale:				{ return_value.set_float(1.0f);  break; }
		case _currentframe:			{ return_value.set_int(m_Actualframe);  break; }
		case _totalframes:			{ return_value.set_int(m_frameNumber);  break; }
		case _alpha:				{ return_value.set_float(1.0f);  break; }
		case _visible:				{ return_value.set_bool(true);  break; }
		case _width:				{ return_value.set_float( m_frameSize.width() );  break; }
		case _height:				{ return_value.set_float( m_frameSize.height() );  break; }
		case _rotation:				{ return_value.set_float( 0.0f );  break; }
		case _target:				{ return_value.set_str( s_empty_string );  break; }
		case _framesloaded:			{ return_value.set_int( m_frameNumber );  break; }
		case _name:					{ return_value.set_str( s_empty_string );  break; }
		case _droptarget:			{ return_value.set_str( s_empty_string );  break; }
		case _url:					{ return_value.set_str( s_empty_string );  break; }
		case _highquality:			{ return_value.set_bool( true );  break; }
		case _focusrect:			{ return_value.set_float( 0.0f );  break; }
		case _soundbuftime:			{ return_value.set_float( 0.0f );  break; }
		case _quality:				{ return_value.set_int( 1 );  break; }
		case _xmouse:				{ return_value.set_float( 0.0f );  break; }
		case _ymouse:				{ return_value.set_float( 0.0f );  break; }
		}
		return return_value;
	}

	void LightFile::setProperty(PropertyEnum property, const As2Var& value ){
		switch( property ){
		default: break;
		case _X:					{ /*Do Nothing*/  break; }
		case _Y:					{ /*Do Nothing*/  break; }
		case _xscale:				{ /*Do Nothing*/  break; }
		case _yscale:				{ /*Do Nothing*/  break; }
		case _currentframe:			{ /*Do Nothing*/  break; }
		case _totalframes:			{ /*Do Nothing*/  break; }
		case _alpha:				{ /*Do Nothing*/  break; }
		case _visible:				{ /*Do Nothing*/  break; }
		case _width:				{ /*Do Nothing*/  break; }
		case _height:				{ /*Do Nothing*/  break; }
		case _rotation:				{ /*Do Nothing*/  break; }
		case _target:				{ /*Do Nothing*/  break; }
		case _framesloaded:			{ /*Do Nothing*/  break; }
		case _name:					{ /*Do Nothing*/  break; }
		case _droptarget:			{ /*Do Nothing*/  break; }
		case _url:					{ /*Do Nothing*/  break; }
		case _highquality:			{ /*Do Nothing*/  break; }
		case _focusrect:			{ /*Do Nothing*/  break; }
		case _soundbuftime:			{ /*Do Nothing*/  break; }
		case _quality:				{ /*Do Nothing*/  break; }
		case _xmouse:				{ /*Do Nothing*/  break; }
		case _ymouse:				{ /*Do Nothing*/  break; }
		}
	}

};
